#!/usr/bin/python3
import serial
import threading
import queue

class Master(threading.Thread):
    auchCRCHi = bytearray([
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
        0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
        0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
        0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
        0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
        0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
        0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
        0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
        0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40]
    )
    auchCRCLo = bytearray([
        0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
        0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
        0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
        0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
        0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
        0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
        0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
        0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
        0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
        0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
        0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
        0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
        0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
        0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
        0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
        0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
        0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
        0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
        0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
        0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
        0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
        0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
        0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
        0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
        0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
        0x43, 0x83, 0x41, 0x81, 0x80, 0x40
    ])

    #modbus从设备地址
    modbus_addr = 1

    #串口
    modbus_serial = serial.Serial()

    #接收结果
    modbus_queue = queue.Queue(1)

    #初始化函数
    def __init__(self, port, baudrate):
        super(Master, self).__init__()
        self.modbus_serial.port = port
        self.modbus_serial.baudrate = baudrate
        if not self.modbus_serial.is_open:
            try:
                self.modbus_serial.open()
            except ZeroDivisionError as e:
                print(e)
        else:
            print("serialport is open!\r\n")
        return

    #协议栈开始
    def master_stack_start(self):
        #modbus_thread = threading.Thread(target=self.modbus_recv_thread(), name="modbus_recv_thread")
        #modbus_thread.start()
        self.start()

    def run(self):
        self.modbus_recv_thread()

    #设置串口参数
    def set_serialport_param(self, port, baudrate):
        self.modbus_serial.port = port
        self.modbus_serial.baudrate = baudrate
        if not self.modbus_serial.is_open:
            self.modbus_serial.open()
        else:
            print("serialport is open!\r\n")
        return

    #计算modbus crc16校验码
    def modbus_crc16(self, msg, length):
        crc_hi = 0xFF # 高CRC字节初始化
        crc_lo = 0xFF # 低CRC字节初始化
        i = 0         # CRC循环中的索引
        while length:
            index = crc_hi ^ msg[i] # 计算CRC
            crc_hi = crc_lo ^ self.auchCRCHi[index]
            crc_lo = self.auchCRCLo[index]
            length -= 1
            i += 1
        crc = (crc_hi << 8 | crc_lo)
        return crc

    #modbus 发送数据
    def  modbus_send_data(self, data_arry):
        if self.modbus_serial.is_open:
            self.modbus_serial.write(data_arry)
        #for i in range(bytes(data_arry).__len__()):
        #    print("%02X " %data_arry[i], end="")
        #print("")
        return

    #设备地址[1] 功能码[1] 线圈起始地址[2] 线圈个数[2] crc校验[2]
    def modbus_read_coil(self, start_addr, coil_num):
        if not(isinstance(start_addr, int)) or not(isinstance(coil_num, int)):
            return
        send_data = bytearray(8)
        send_data[0] = self.modbus_addr
        send_data[1] = 0x01
        send_data[2] = (start_addr >> 8) & 0xFF
        send_data[3] = start_addr & 0xFF
        send_data[4] = (coil_num >> 8) & 0xFF
        send_data[5] = coil_num & 0xFF
        crc = self.modbus_crc16(send_data, 6)
        send_data[6] = (crc >> 8) & 0xFF
        send_data[7] = crc & 0xFF
        self.modbus_send_data(send_data)
        try:
            # 设备地址[1] 功能码[1] 字节数[1] 线圈[N] crc校验[2]
            recv_bytes = self.modbus_queue.get(True, 1)
            calc_crc = self.modbus_crc16(recv_bytes, bytes(recv_bytes).__len__() - 2)
            recv_crc = (recv_bytes[bytes(recv_bytes).__len__() - 2] << 8) + recv_bytes[bytes(recv_bytes).__len__() - 1]
            if (recv_bytes[0] == self.modbus_addr) and (recv_bytes[1] == 0x01) and (calc_crc == recv_crc):
                ret_coils = []
                for index in range(recv_bytes[2]):
                    byte_index = 3 + (int)(index / 8)
                    if (recv_bytes[byte_index] & (1 << (index % 8)))>0:
                        ret_coils.append(1)
                    else:
                        ret_coils.append(0)
                    index += 1
                return ret_coils
            else :
                return
        except :
            return

    #设备地址[1] 功能码[1] 输入状态起始地址[2] 输入状态个数[2] crc校验[2]
    def modbus_read_input_status(self, start_addr, input_status_num):
        if not(isinstance(start_addr, int)) or not(isinstance(input_status_num, int)):
            return
        send_data = bytearray(8)
        send_data[0] = self.modbus_addr
        send_data[1] = 0x02
        send_data[2] = (start_addr >> 8) & 0xFF
        send_data[3] = start_addr & 0xFF
        send_data[4] = (input_status_num >> 8) & 0xFF
        send_data[5] = input_status_num & 0xFF
        crc = self.modbus_crc16(send_data, 6)
        send_data[6] = (crc >> 8) & 0xFF
        send_data[7] = crc & 0xFF
        self.modbus_send_data(send_data)
        try:
            # 设备地址[1] 功能码[1] 字节数[1] 输入状态[N] crc校验[2]
            recv_bytes = self.modbus_queue.get(True, 1)
            if bytes(recv_bytes).__len__() < 6:
                return
            calc_crc = self.modbus_crc16(recv_bytes, bytes(recv_bytes).__len__() - 2)
            recv_crc = (recv_bytes[bytes(recv_bytes).__len__() - 2] << 8) + recv_bytes[bytes(recv_bytes).__len__() - 1]
            if (recv_bytes[0] == self.modbus_addr) and (recv_bytes[1] == 0x02) and (calc_crc == recv_crc):
                ret_input_status = []
                for index in range(recv_bytes[2]):
                    byte_index = 3 + (int)(index / 8)
                    if recv_bytes[byte_index] & 1 << (index % 8):
                        ret_input_status.append(1)
                    else:
                        ret_input_status.append(0)
                return ret_input_status
            else :
                return
        except :
            return

    # 设备地址[1] 功能码[1] 保持寄存器起始地址[2] 保持寄存器个数[2] crc校验[2]
    def modbus_read_hold_reg(self, start_addr, hold_reg_num):
        if not(isinstance(start_addr, int)) or not(isinstance(hold_reg_num, int)):
            return
        send_data = bytearray(8)
        send_data[0] = self.modbus_addr
        send_data[1] = 0x03
        send_data[2] = (start_addr >> 8) & 0xFF
        send_data[3] = start_addr & 0xFF
        send_data[4] = (hold_reg_num >> 8) & 0xFF
        send_data[5] = hold_reg_num & 0xFF
        crc = self.modbus_crc16(send_data, 6)
        send_data[6] = (crc >> 8) & 0xFF
        send_data[7] = crc & 0xFF
        self.modbus_send_data(send_data)
        try:
            # 设备地址[1] 功能码[1] 字节数[1] 保持寄存器[N] crc校验[2]
            recv_bytes = self.modbus_queue.get(True, 1)
            if bytes(recv_bytes).__len__() < 6:
                return
            calc_crc = self.modbus_crc16(recv_bytes, bytes(recv_bytes).__len__() - 2)
            recv_crc = (recv_bytes[bytes(recv_bytes).__len__() - 2] << 8) + recv_bytes[bytes(recv_bytes).__len__() - 1]
            if (recv_bytes[0] == self.modbus_addr) and (recv_bytes[1] == 0x03) and (calc_crc == recv_crc):
                ret_hold_reg = []
                for index in range(hold_reg_num):
                        hold_reg_value = (recv_bytes[3 + index*2] << 8) + recv_bytes[4 + index*2]
                        ret_hold_reg.append(hold_reg_value)
                return ret_hold_reg
            else :
                return
        except :
            return

    # 设备地址[1] 功能码[1] 输入寄存器起始地址[2] 输入寄存器个数[2] crc校验[2]
    def modbus_read_input_reg(self, start_addr, input_reg_num):
        if not(isinstance(start_addr, int)) or not(isinstance(input_reg_num, int)):
            return
        send_data = bytearray(8)
        send_data[0] = self.modbus_addr
        send_data[1] = 0x04
        send_data[2] = (start_addr >> 8) & 0xFF
        send_data[3] = start_addr & 0xFF
        send_data[4] = (input_reg_num >> 8) & 0xFF
        send_data[5] = input_reg_num & 0xFF
        crc = self.modbus_crc16(send_data, 6)
        send_data[6] = (crc >> 8) & 0xFF
        send_data[7] = crc & 0xFF
        self.modbus_send_data(send_data)
        try:
            # 设备地址[1] 功能码[1] 字节数[1] 输入寄存器[N] crc校验[2]
            recv_bytes = self.modbus_queue.get(True, 1)
            if bytes(recv_bytes).__len__() < 6:
                return
            calc_crc = self.modbus_crc16(recv_bytes, bytes(recv_bytes).__len__() - 2)
            recv_crc = (recv_bytes[bytes(recv_bytes).__len__() - 2] << 8) + recv_bytes[bytes(recv_bytes).__len__() - 1]
            if (recv_bytes[0] == self.modbus_addr) and (recv_bytes[1] == 0x04) and (calc_crc == recv_crc):
                ret_input_reg = []
                for index in range(input_reg_num):
                    input_reg_value = (recv_bytes[3 + index*2] << 8) + recv_bytes[4 + index*2]
                    ret_input_reg.append(input_reg_value)
                return ret_input_reg
            else :
                return
        except :
            return

    # 设备地址[1] 功能码[1] 线圈起始地址[2] 线圈值[2] crc校验[2]
    def modbus_write_single_coil(self, start_addr, coil_value):
        if not(isinstance(start_addr, int)) or not(isinstance(coil_value, int)):
            return
        send_data = bytearray(8)
        send_data[0] = self.modbus_addr
        send_data[1] = 0x05
        send_data[2] = (start_addr >> 8) & 0xFF
        send_data[3] = start_addr & 0xFF
        send_data[4] = (coil_value >> 8) & 0xFF
        send_data[5] = coil_value & 0xFF
        crc = self.modbus_crc16(send_data, 6)
        send_data[6] = (crc >> 8) & 0xFF
        send_data[7] = crc & 0xFF
        self.modbus_send_data(send_data)
        try:
            recv_bytes = self.modbus_queue.get(True, 1)
            calc_crc = self.modbus_crc16(recv_bytes, bytes(recv_bytes).__len__() - 2)
            recv_crc = (recv_bytes[bytes(recv_bytes).__len__() - 2] << 8) + recv_bytes[bytes(recv_bytes).__len__() - 1]
            if (recv_bytes[0] == self.modbus_addr) and (recv_bytes[1] == 0x05) and (calc_crc == recv_crc):
                return 1
            else :
                return
        except :
            return

    # 设备地址[1] 功能码[1] 保持寄存器起始地址[2] 保持寄存器值[2] crc校验[2]
    def modbus_write_single_reg(self, start_addr, reg_value):
        if not(isinstance(start_addr, int)) or not(isinstance(reg_value, int)):
            return
        send_data = bytearray(8)
        send_data[0] = self.modbus_addr
        send_data[1] = 0x06
        send_data[2] = (start_addr >> 8) & 0xFF
        send_data[3] = start_addr & 0xFF
        send_data[4] = (reg_value >> 8) & 0xFF
        send_data[5] = reg_value & 0xFF
        crc = self.modbus_crc16(send_data, 6)
        send_data[6] = (crc >> 8) & 0xFF
        send_data[7] = crc & 0xFF
        self.modbus_send_data(send_data)
        try:
            recv_bytes = self.modbus_queue.get(True, 1)
            calc_crc = self.modbus_crc16(recv_bytes, bytes(recv_bytes).__len__() - 2)
            recv_crc = (recv_bytes[bytes(recv_bytes).__len__() - 2] << 8) + recv_bytes[bytes(recv_bytes).__len__() - 1]
            if (recv_bytes[0] == self.modbus_addr) and (recv_bytes[1] == 0x06) and (calc_crc == recv_crc):
                return 1
            else :
                return
        except :
            return

    # 设备地址[1] 功能码[1] 线圈起始地址[2] 线圈个数[2] 写入字节数[1] 线圈值[N] crc校验[2]
    def modbus_write_mutil_coils(self, start_addr, coils_num, coil_values):
        if not(isinstance(start_addr, int)) or not(isinstance(coils_num, int)) or not(isinstance(coil_values, bytearray)):
            return
        send_data = bytearray(10 + (coils_num / 8))
        send_data[0] = self.modbus_addr
        send_data[1] = 0x0F
        send_data[2] = (start_addr >> 8) & 0xFF
        send_data[3] = start_addr & 0xFF
        send_data[4] = (coils_num >> 8) & 0xFF
        send_data[5] = coils_num & 0xFF
        send_data[6] = coils_num / 8
        index = 7
        for i in range(coils_num):
            send_data[index] = coil_values[i]
            index += 1
        crc = self.modbus_crc16(send_data, index)
        send_data[index] = (crc >> 8) & 0xFF
        send_data[index + 1] = crc & 0xFF
        self.modbus_send_data(send_data)
        try:
            recv_bytes = self.modbus_queue.get(True, 1)
            calc_crc = self.modbus_crc16(recv_bytes, bytes(recv_bytes).__len__() - 2)
            recv_crc = (recv_bytes[bytes(recv_bytes).__len__() - 2] << 8) + recv_bytes[bytes(recv_bytes).__len__() - 1]
            if (recv_bytes[0] == self.modbus_addr) and (recv_bytes[1] == 0x0F) and (calc_crc == recv_crc):
                return 1
            else :
                return
        except :
            return

    # 设备地址[1] 功能码[1] 保持寄存器起始地址[2] 保持寄存器个数[2] 写入字节数[1] 保持寄存器值[N] crc校验[2]
    def modbus_write_mutil_hold_reg(self, start_addr, hold_reg_num, hold_reg_values):
        if not(isinstance(start_addr, int)) or not(isinstance(hold_reg_num, int)) or not(isinstance(hold_reg_values, bytearray)):
            return
        send_data = bytearray(10 + (hold_reg_num * 2))
        send_data[0] = self.modbus_addr
        send_data[1] = 0x10
        send_data[2] = (start_addr >> 8) & 0xFF
        send_data[3] = start_addr & 0xFF
        send_data[4] = (hold_reg_num >> 8) & 0xFF
        send_data[5] = hold_reg_num & 0xFF
        send_data[6] = hold_reg_num * 2
        index = 7
        for i in range(hold_reg_num):
            send_data[index] = (hold_reg_values[i] >> 8) & 0xFF
            index += 1
            send_data[index] = hold_reg_values[i] & 0xFF
            index += 1
        crc = self.modbus_crc16(send_data, index)
        send_data[index] = (crc >> 8) & 0xFF
        send_data[index + 1] = crc & 0xFF
        self.modbus_send_data(send_data)
        try:
            recv_bytes = self.modbus_queue.get(True, 1)
            calc_crc = self.modbus_crc16(recv_bytes, bytes(recv_bytes).__len__() - 2)
            recv_crc = (recv_bytes[bytes(recv_bytes).__len__() - 2] << 8) + recv_bytes[bytes(recv_bytes).__len__() - 1]
            if (recv_bytes[0] == self.modbus_addr) and (recv_bytes[1] == 0x10) and (calc_crc == recv_crc):
                return 1
            else :
                return
        except :
            return

    #modbus接收串口的数据
    def modbus_recv_thread(self):
        recv_bytes = bytes()
        while True:
            while self.modbus_serial.inWaiting() > 0:
                recv_bytes += self.modbus_serial.read(1)
            if recv_bytes != bytes():
                #for i in range(bytes(recv_bytes).__len__()):
                #    print("%02X " % recv_bytes[i], end="")
                #print("")
                self.modbus_queue.put(recv_bytes)
                recv_bytes = bytes()

class Slave(threading.Thread):
    auchCRCHi = bytearray([
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
        0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
        0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
        0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
        0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
        0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
        0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
        0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
        0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40]
    )
    auchCRCLo = bytearray([
        0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
        0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
        0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
        0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
        0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
        0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
        0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
        0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
        0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
        0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
        0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
        0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
        0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
        0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
        0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
        0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
        0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
        0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
        0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
        0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
        0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
        0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
        0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
        0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
        0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
        0x43, 0x83, 0x41, 0x81, 0x80, 0x40
    ])

    # modbus从设备地址
    modbus_addr = 1

    # 串口
    modbus_serial = serial.Serial()

    # 接收结果
    modbus_queue = queue.Queue(1)

    # 初始化函数
    def __init__(self, port, baudrate):
        super(Slave, self).__init__()
        self.modbus_serial.port = port
        self.modbus_serial.baudrate = baudrate
        if not self.modbus_serial.is_open:
            try:
                self.modbus_serial.open()
            except ZeroDivisionError as e:
                print(e)
        else:
            print("serialport is open!\r\n")
        return

    # 协议栈开始
    def master_stack_start(self):
        self.start()

    def run(self):
        self.modbus_recv_thread()

    # 设置串口参数
    def set_serialport_param(self, port, baudrate):
        self.modbus_serial.port = port
        self.modbus_serial.baudrate = baudrate
        if not self.modbus_serial.is_open:
            self.modbus_serial.open()
        else:
            print("serialport is open!\r\n")
        return

    # 计算modbus crc16校验码
    def modbus_crc16(self, msg, length):
        crc_hi = 0xFF  # 高CRC字节初始化
        crc_lo = 0xFF  # 低CRC字节初始化
        i = 0  # CRC循环中的索引
        while length:
            index = crc_hi ^ msg[i]  # 计算CRC
            crc_hi = crc_lo ^ self.auchCRCHi[index]
            crc_lo = self.auchCRCLo[index]
            length -= 1
            i += 1
        crc = (crc_hi << 8 | crc_lo)
        return crc

    # modbus 发送数据
    def modbus_send_data(self, data_arry):
        if self.modbus_serial.is_open:
            self.modbus_serial.write(data_arry)
        # for i in range(bytes(data_arry).__len__()):
        #    print("%02X " %data_arry[i], end="")
        # print("")
        return

    #modbus接收串口的数据
    def modbus_recv_thread(self):
        recv_bytes = bytes()
        while True:
            while self.modbus_serial.inWaiting() > 0:
                recv_bytes += self.modbus_serial.read(1)
            if recv_bytes != bytes():
                #for i in range(bytes(recv_bytes).__len__()):
                #    print("%02X " % recv_bytes[i], end="")
                #print("")
                self.modbus_queue.put(recv_bytes)
                recv_bytes = bytes()